package com.benio.ycfdisplayer.fresco;

import android.net.Uri;
import android.text.TextUtils;

import com.benio.ycfdisplayer.displayer.DisplayListener;
import com.benio.ycfdisplayer.displayer.Executor;
import com.benio.ycfdisplayer.displayer.Options;
import com.benio.ycfdisplayer.displayer.Request;
import com.benio.ycfdisplayer.displayer.Target;
import com.facebook.common.executors.UiThreadImmediateExecutorService;
import com.facebook.common.internal.Preconditions;
import com.facebook.common.references.CloseableReference;
import com.facebook.datasource.DataSource;
import com.facebook.datasource.DataSubscriber;
import com.facebook.drawee.backends.pipeline.Fresco;
import com.facebook.imagepipeline.image.CloseableImage;
import com.facebook.imagepipeline.request.ImageRequest;

/**
 * An Executor that only loads Bitmap.
 * <p>
 * https://www.fresco-cn.org/docs/datasources-datasubscribers.html
 * Created by zhangzhibin on 2016/12/20.
 */
public class BitmapExecutor implements Executor {

    public BitmapExecutor() {
    }

    @Override
    public void execute(Request request) {
        Preconditions.checkNotNull(request, "Request cannot be null");
        final Target target = request.getTarget();
        final String uriString = request.getUri();
        final DisplayListener listener = request.getDisplayListener();
        final Options options = request.getOptions();
        execute(uriString, target, options, listener);
    }

    protected void execute(String uriString, Target target, Options options, DisplayListener listener) {
        Uri uri = TextUtils.isEmpty(uriString) ? null : Uri.parse(uriString);
        ImageRequest imageRequest = FrescoOptionsApplier.newImageRequest(uri, options);
        DataSource<CloseableReference<CloseableImage>> dataSource = Fresco.getImagePipeline().fetchDecodedImage(imageRequest, null);
        DataSubscriber<CloseableReference<CloseableImage>> dataSubscriber = new BitmapDataSubscriber(uriString, target, options, listener);
        dataSource.subscribe(dataSubscriber, UiThreadImmediateExecutorService.getInstance());
    }

    /**
     * Removes all images with the specified {@link Uri} from memory cache.
     *
     * @param uri The uri of the image to evict
     */
    public void evictFromMemoryCache(final Uri uri) {
        if (uri != null) {
            Fresco.getImagePipeline().evictFromMemoryCache(uri);
        }
    }

    /**
     * <p>If you have supplied your own cache key factory when configuring the pipeline, this method
     * may not work correctly. It will only work if the custom factory builds the cache key entirely
     * from the URI.
     *
     * @param uri The uri of the image to evict
     */
    public void evictFromDiskCache(final Uri uri) {
        if (uri != null) {
            Fresco.getImagePipeline().evictFromDiskCache(uri);
        }
    }

    /**
     * <p>If you have supplied your own cache key factory when configuring the pipeline, this method
     * may not work correctly. It will only work if the custom factory builds the cache key entirely
     * from the URI. If that is not the case, use {@link #evictFromMemoryCache(Uri)}
     *
     * @param uri The uri of the image to evict
     */
    public void evictFromCache(final Uri uri) {
        if (uri != null) {
            Fresco.getImagePipeline().evictFromCache(uri);
        }
    }

    /**
     * Clear the memory caches
     */
    public void clearMemoryCaches() {
        Fresco.getImagePipeline().clearMemoryCaches();
    }

    /**
     * Clear disk caches
     */
    public void clearDiskCaches() {
        Fresco.getImagePipeline().clearDiskCaches();
    }

    /**
     * Clear all the caches (memory and disk)
     */
    public void clearCaches() {
        Fresco.getImagePipeline().clearCaches();
    }

    /**
     * Returns whether the image is stored in the bitmap memory cache.
     *
     * @param uri the uri for the image to be looked up.
     * @return true if the image was found in the bitmap memory cache, false otherwise
     */
    public boolean isInBitmapMemoryCache(final Uri uri) {
        return uri != null && Fresco.getImagePipeline().isInBitmapMemoryCache(uri);
    }

    /**
     * Returns whether the image is stored in the disk cache.
     * Performs disk cache check synchronously. It is not recommended to use this
     * unless you know what exactly you are doing. Disk cache check is a costly operation,
     * the call will block the caller thread until the cache check is completed.
     *
     * @param uri the uri for the image to be looked up.
     * @return true if the image was found in the disk cache, false otherwise.
     */
    public boolean isInDiskCacheSync(final Uri uri) {
        return uri != null && Fresco.getImagePipeline().isInDiskCacheSync(uri);
    }

    public void pause() {
        Fresco.getImagePipeline().pause();
    }

    public void resume() {
        Fresco.getImagePipeline().resume();
    }

    public boolean isPaused() {
        return Fresco.getImagePipeline().isPaused();
    }
}
